/*这段代码的作用是创建多个线程并实现线程之间的同步。

具体的实现流程如下：

定义了宏常量NUM，用于指定线程的数量，以及JOBS和DELAY分别表示每个线程要执行的作业数量和作业执行的最大延迟时间。
声明了一个全局的信号量数组sem[NUM]，用于实现线程之间的同步。
定义了线程函数thrd_func，每个线程通过调用该函数执行一定数量的作业。在每个作业执行之前，线程会等待前一个线程的信号量，以保证线程的执行顺序。
在main函数中，创建了NUM个线程，并将线程ID存储在tid[NUM]数组中。每个线程的序号作为参数传递给线程函数。
在创建线程后，使用pthread_join函数等待所有线程执行完毕。
最后，使用sem_destroy函数销毁信号量数组。

通过信号量的使用，代码实现了线程之间的同步。每个线程在执行作业之前会等待前一个线程释放信号量，从而保证线程按照预定的顺序执行作业。这样可以实现线程间的协调和同步，确保线程按照指定的顺序执行作业。*/

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>

#define NUM 3
#define JOBS 5
#define DELAY 5

sem_t sem[NUM];

void *thrd_func(void *arg){
    long int seq = (long int)arg;
    int delay_time = 0;
    int i;

    // 等待前一个线程的信号量
    sem_wait(&sem[seq]);

    printf("Thread %d is running.\n", seq);

    for(i = 0; i < JOBS; i++){
        delay_time = (int)(DELAY * (rand() / (double)RAND_MAX)) + 1;

        sleep(delay_time);
        printf("\tThread %d, job:%d, delay:%d.\n", seq, i, delay_time);
    }

    printf("Thread %d finished.\n", seq);

    // 释放下一个线程的信号量
    sem_post(&sem[(seq + NUM - 1) % NUM]);

    return 0;
}


int main(){
    pthread_t tid[NUM];
    long int no;
    int i;

    srand((int)time(0));

    // 初始化信号量
    sem_init(&sem[0], 0, 0);
    sem_init(&sem[1], 0, 0);
    sem_init(&sem[2], 0, 1);

    for(no = 0; no < NUM; no++){    
        if(pthread_create(&tid[no], NULL, thrd_func, (void*)no) != 0){   
            perror("pthread create");
            exit(-1);
        }
        printf("Create thread %d.\n", no);
    }

    for(no = 0; no < NUM; no++){    
        if(pthread_join(tid[no], NULL) != 0){
            perror("pthread exit");
            exit(-1);
        }
    }
    
    for(i = 0; i < NUM; i++)
        sem_destroy(&sem[i]);   

    return 0;
}
